﻿////////////////////////////////////////////////////
/// This file is part of Marstone Code Studio    ///
///    Copyright(c)2007 - 2008, Marstone Studio  ///
///           Author: marstone                   ///
///       Email: marstone@marstone.net           ///
///           Since: 2007 SqlInjector            ///
////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace Studio.Windows.UserControls
{
    public partial class OutputConsole : UserControl
    {
        string prefix = string.Empty;
        /// <summary>
        /// Prefix used by OutputLine.
        /// </summary>
        public string Prefix
        {
            get { return prefix; }
            set { prefix = value; }
        }

        public OutputConsole()
        {
            InitializeComponent();
            OutputCls();
        }

        delegate void OutputCallback(string message);

        
        #region Output Management

        /// <summary>
        /// log file name, if 
        /// </summary>
        private string _logFileName = Application.ProductName + ".log";

        public string LogFileName
        {
            get { return _logFileName; }
            set { _logFileName = value; }
        }

        bool _isLogToFile = false;

        public bool IsLogToFile
        {
            get { return _isLogToFile; }
            set { _isLogToFile = value; }
        }


        StreamWriter _logWriter = null;

        private string _welcomeMessage = "Marstone Studio Output Console, Powered by Marstone.NET, 2008\r\n";

        public string WelcomeMessage
        {
            get { return _welcomeMessage; }
            set { _welcomeMessage = value; }
        }


        private int _maxLine = 256;

        public int MaxLine
        {
            get { return _maxLine; }
            set { _maxLine = value; }
        }
        public void Output(string format, params object[] args)
        {
            this.Output(string.Format(format, args));
        }

        /// <summary>
        /// Output a message to Output Console
        /// </summary>
        public void Output(string message)
        {
            // Return immediately if Control is Disposed. Added by marstone, 2008/12/04
            if (true == textBoxOutput.IsDisposed) return;

            if (textBoxOutput.InvokeRequired)
            {
                OutputCallback callback = new OutputCallback(Output);
                this.Invoke(callback, new object[] { message });
            }
            else
            {
                OutputFile(message, _logFileName);
            }
        }

        public void OutputLine(string format, params object[] args)
        {
            this.OutputLine(string.Format(format, args));
        }

        /// <summary>
        /// Output a string and then switch to next line
        /// </summary>
        public void OutputLine(string message)
        {
            Output(this.Prefix + message + "\r\n");
        }

        /// <summary>
        /// Output "\r\n"
        /// </summary>
        public void OutputLine()
        {
            Output("\r\n");
        }

        private void OutputCls(string logFileName)
        {
            OutputCls();
            OutputFile(null, Int32.MaxValue, _logFileName, true);
        }

        private void OutputFile(string message, string logFileName)
        {
            OutputFile(message, _maxLine, logFileName, true);
        }
        
        private void OutputFile(string message, int maxLine, string logFileName, bool isAppend)
        {
            if (true == isAppend)
            {
                // Delete Previous Lines
                if (maxLine <= textBoxOutput.Lines.Length)
                {
                    // Remove 10 lines once.
                    int LineToRemove = Math.Min(10, maxLine);
                    
                    int Count = 0;
                    for (int i = 0; i < LineToRemove; i++)
                    {
                        Count += textBoxOutput.Lines[i].Length;
                    }
                    Count += 2 * LineToRemove;
                    textBoxOutput.Text = textBoxOutput.Text.Remove(0, Count);
                }
            }
            else
                this.OutputCls();

            // Output to Screen
            textBoxOutput.AppendText(message);

            // Output to File?
            if (false == string.IsNullOrEmpty(logFileName) && true == _isLogToFile)
            {
                // Write to log file
                StreamWriter writer = _logWriter;
                try
                {
                    if (null == writer) writer = new StreamWriter(logFileName, isAppend);
                    if (null != writer) writer.WriteLine("{0} -- {1}", DateTime.Now, message);
                }
                catch (Exception ex)
                {
                    this.OutputFile(string.Format("{0} -- Exception: {1}", DateTime.Now, ex.Message), null);
                    if (null != writer) writer.WriteLine("{0} -- Exception: {1}", DateTime.Now, ex.Message);
                }
                finally
                {
                    // if (null != writer) writer.Close();
                    // if we open the writer, we should close it.
                    if (null != writer && null == _logWriter) writer.Close();
                }
            }
        }


        private void OutputCls()
        {
            if (true == textBoxOutput.IsDisposed) return;
            textBoxOutput.Text = WelcomeMessage;
        }

        #endregion

        private void clearToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OutputCls();
        }

        /// <summary>
        /// Set this.Font to the Output TextBox
        /// </summary>
        public override Font Font
        {
            get { return base.Font; }
            set { base.Font = value; this.textBoxOutput.Font = value; }
        }

        private void searchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SearchBox search = new SearchBox();
            search.ShowDialog();
        }

        private void readOnlyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.textBoxOutput.ReadOnly = (sender as ToolStripMenuItem).Checked = !(sender as ToolStripMenuItem).Checked;
        }

        private void fontToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FontDialog dialog = new FontDialog();
            dialog.Font = this.Font;
            if (DialogResult.OK == dialog.ShowDialog()) this.Font = dialog.Font;
        }

    }
}
